#pragma once




//see lsusb_output
#define BULK_EP_IN  0x81
#define BULK_EP_OUT 0x02
#define INT_EP_IN   0x83
#define RQ_TIMEOUT  5000

//Control register states
static const unsigned char state_00_80_00_30[4] = { 0x00, 0x80, 0x00, 0x30 };
static const unsigned char state_00_80_02_30[4] = { 0x00, 0x80, 0x02, 0x30 };
static const unsigned char state_00_80_03_30[4] = { 0x00, 0x80, 0x03, 0x30 };//in idle
static const unsigned char state_00_c0_03_30[4] = { 0x00, 0xc0, 0x03, 0x30 };
static const unsigned char state_38_b0_00_30[4] = { 0x38, 0xb0, 0x00, 0x30 };
static const unsigned char state_40_a8_00_30[4] = { 0x40, 0xa8, 0x00, 0x30 };//after init
static const unsigned char state_40_a8_02_30[4] = { 0x40, 0xa8, 0x02, 0x30 };//interrupt
static const unsigned char state_40_b0_00_30[4] = { 0x40, 0xb0, 0x00, 0x30 };


#define CONTROL_INIT    0x0400
#define CONTROL_TO_IDLE 0x0602
#define CONTROL_WAKE_UP 0x0601


#define RAMFLAG_SCAN    0x00
#define RAMFLAG_DEFAULT 0x01


#define ACTION_READ ( 1 << 7 )
#define ACTION_SEND ( 1 << 6 )
#define ACT_ERR_IGN ( 1 << 5 )

struct packet_sequence_map{
	
	unsigned char action;
	unsigned char type;
	int           messageLength;
	
	const unsigned char* data;
};

//init
static const unsigned char init_packet1_in[5] =  { 0x01, 0x62, 0x30, 0x2e, 0x32 };//static
static const unsigned char init_packet2_out[8] = { 0x01, 0x00, 0xbc, 0x02, 0x00, 0x00, 0x00, 0x00 };//static
static const unsigned char init_packet3_in[1] =  { 0x01 };//static

//3-way challenge-response authentication?
static const unsigned char init_packet_28_06_out[7] = { 0x28, 0x04, 0x00, 0x00, 0x00, 0x06, 0x04 };//static
static const unsigned char init_packet_28_06_in[55] = {//static
	0x28, 0x34, 0x00, 0x00, 0x00, 0x06, 0x14, 0x14,     0x02, 0x01, 0x04, 0x14, 0x02, 0x01, 0x04, 0x0d, 
	0x00, 0x00, 0x00, 0x69, 0x00, 0x03, 0x00, 0x10,     0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,     0x00, 0x00, 0xc0, 0xc0, 0x00, 0x68, 0x01, 0x00, 
	0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00 };

static const unsigned char init_packet_28_07_out[11] ={ 0x28, 0x08, 0x00, 0x00, 0x00, 0x07, 0x04, 0x08, 0x00, 0x00, 0x00 };//static
//28_07_in dynamic

static const unsigned char init_packet_28_08_out[31] = {//dynamic
	0x28, 0x1c, 0x00, 0x00, 0x00, 0x08, 0x04, 0x56,     0xf1, 0x59, 0xd5, 0x03, 0x12, 0xcd, 0x78, 0x70,
	0x37, 0x21, 0x3f, 0x84, 0xf3, 0xf1, 0x98, 0x39,     0xfe, 0x16, 0xb4, 0xac, 0x75, 0xa9, 0x9c, };
//28_08_in dynamic


static const unsigned char fake_cmd[1] = { 0x00 };

static const struct packet_sequence_map init_map[] = { 
	//init
	{ ACTION_READ, 3, 5, init_packet1_in },//0
	{ ACTION_SEND, 4, 8, init_packet2_out},//1
	{ ACTION_READ, 5, 1, init_packet3_in },//2
	
	//3-way challenge-response authentication?
	{ ACTION_SEND,               0, 7,  init_packet_28_06_out },//3
	{ ACTION_READ,               0, 55, init_packet_28_06_in  },//4
	{ ACTION_SEND,               0, 11, init_packet_28_07_out },//5
	{ ACTION_READ | ACT_ERR_IGN, 0, 15, fake_cmd              },//6
	{ ACTION_SEND,               0, 31, init_packet_28_08_out },//7
	{ ACTION_READ | ACT_ERR_IGN, 0, 15, fake_cmd              },//8
	
	//{ ACTION_, type, len, data, },
	
	{ .action = 0x00 }//list terminator
};



//ram write ( subcmd 0x0b )
unsigned char ramWriteRequest[15] = { 0x28, 0x6c, 0x00, 0x00, 0x00, 0x0b, 0x04, 0x03, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00 };
unsigned char ramWriteResponse[7] = { 0x28, 0x04, 0x00, 0x00, 0x00, 0x0b, 0x14 };


//ram read ( subcmd 0x0c )
unsigned char ramReadRequest[11]  = { 0x28, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x04, 0x03, 0x00, 0x00, 0x00 };
unsigned char ramReadResponse[11] = { 0x28, 0x68, 0x00, 0x00, 0x00, 0x0c, 0x14, 0x60, 0x00, 0x00, 0x00 };


//finger scan ( subcmd 0x0e )
static const unsigned char finger_scan_response_picture[11] = { 0x2c, 0xe8, 0x97, 0x00, 0x00, 0x0e, 0x12, 0xe0, 0x97, 0x00, 0x00 };
static const unsigned char finger_scan_response_canceled[7] = { 0x28, 0x04, 0x00, 0xe4, 0xfb, 0x0e, 0x12 };
static const unsigned char finger_scan_response_timeout[7] =  { 0x28, 0x04, 0x00, 0xe6, 0xfb, 0x0e, 0x12 };
static const unsigned char _finger_scan_poll_response[20] = {
	0x28, 0x11, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01,     0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00 };


//unknown action 1 ( subcmd 0x10 )
static const unsigned char unknown_action1_request[15] = { 0x28, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x02, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const unsigned char unknown_action1_success[7] =  { 0x28, 0x04, 0x00, 0x00, 0x00, 0x10, 0x12 };
static const unsigned char unknown_action1_failure[7] =  { 0x28, 0x04, 0x00, 0xe6, 0xfb, 0x10, 0x12 };


//touchpad ( subcmd 0x12 )
static const unsigned char touchpad_mode_request[11] = { 0x28, 0x08, 0x00, 0x00, 0x00, 0x12, 0x02, 0xff, 0xff, 0xff, 0xff };
static const unsigned char touchpad_mode_response[7] = { 0x28, 0x04, 0x00, 0x00, 0x00, 0x12, 0x12 };


//image quality ( subcmd 0x15 )
static const unsigned char image_quality_request[7] =   { 0x28, 0x04, 0x00, 0x00, 0x00, 0x15, 0x02 };
static const unsigned char image_quality_responce[11] = { 0x28, 0x08, 0x00, 0x00, 0x00, 0x15, 0x12, 0x00, 0x00, 0x00, 0x00 };


//idle mode ( subcmd 0x16 )
static const unsigned char cmd_to_idle[14] =       { 0x28, 0x0b, 0x00, 0x00, 0x00, 0x16, 0x02, 0xf4,    0x01, 0x00, 0x00, 0x02, 0x00, 0x00 };
static const unsigned char idle_answer[15] =       { 0x28, 0x0c, 0x00, 0x00, 0x00, 0x16, 0x12, 0x00,    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 };
static const unsigned char idle_answer_error1[7] = { 0x28, 0x04, 0x00, 0xe6, 0xfb, 0x16, 0x12 };
static const unsigned char idle_answer_error2[7] = { 0x28, 0x04, 0x00, 0xef, 0xfb, 0x16, 0x12 };
static const unsigned char idle_answer_picture[19] = { 
	0x2c, 0xf0, 0x97, 0x00, 0x00, 0x16, 0x12, 0x01,     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
	0x97, 0x00, 0x00 };
